﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web.Mvc;

namespace Cormant.Mvc.Web
{
    public abstract class MvcHtmlTag
    {
        #region Control : Constructors.
        protected MvcHtmlTag(HtmlHelper html, string id)
        {
            if (html == null)
                throw new ArgumentNullException("html");

            HtmlTagAttribute[] attributes = this.GetType().GetCustomAttributes(typeof(HtmlTagAttribute), true) as HtmlTagAttribute[];
            if (attributes == null || attributes.Length == 0)
                throw new InvalidOperationException(string.Format("{0} has no {1}.", this.GetType(), typeof(HtmlTagAttribute)));

            this.Html = html;
            this.Id = id;
            this.TagBuilder = new TagBuilder(attributes[0].TagName);
        }
        #endregion

        #region Control : Properties.
        protected HtmlHelper Html { get; set; }

        public string Id { get; protected set; }

        protected TagBuilder TagBuilder { get; set; }
        #endregion

        #region Control : Methods.
        public override string ToString()
        {
            return this.ToString(TagRenderMode.SelfClosing);
        }

        protected string ToString(TagRenderMode renderMode)
        {
            this.TagBuilder.GenerateId(this.Id);

            PropertyInfo[] properties = this.GetType()
                .GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            foreach (PropertyInfo property in properties)
            {
                object value = property.GetValue(this, null);
                if (value != null)
                {
                    HtmlAttributeAttribute[] attributes = property.GetCustomAttributes(typeof(HtmlAttributeAttribute), true) as HtmlAttributeAttribute[];
                    if (attributes != null && attributes.Length == 1 &&
                        (attributes[0].IgnoredValue == null || !object.Equals(attributes[0].IgnoredValue, value)))
                    {
                        string valueString = value.ToString();
                        if (property.PropertyType == typeof(bool))
                            valueString = valueString.ToLowerInvariant();
                        this.TagBuilder.MergeAttribute(attributes[0].Name, valueString);
                    }
                }
            }

            return this.TagBuilder.ToString(renderMode);
        }
        #endregion
    }
}
